package edu.boun.g4.coursity.service;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import edu.boun.g4.coursity.domain.Course;
import edu.boun.g4.coursity.domain.CoursityUser;

/**
 * 
 * @author mertusta
 * @author bulutkorkmaz
 * @author alifindik
 * 
 */
@Service("courseService")
@Transactional
public class CourseService {

	protected static Logger logger = Logger.getLogger("service");

	@Resource(name = "sessionFactory")
	private SessionFactory sessionFactory;

	/**
	 * Retrieves all courses by their initiatives
	 */
	public List<Course> getByInitiativeId(Integer initiativeId) {
		logger.debug("Retrieving all courses by the initiative id");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = session.createQuery("FROM Course as p LEFT JOIN FETCH  p.initiative WHERE p.initiative.id="
				+ initiativeId);

		List<Course> courses = query.list() ;  

		// Retrieve all
		return courses;
	}

	/**
	 * Retrieves all courses by their institutions
	 */
	public List<Course> getByInstitutionId(Integer institutionId) {
		logger.debug("Retrieving all courses by the institution id");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = session
				.createQuery("FROM Course as p LEFT JOIN FETCH  p.institution WHERE p.institution.id="
						+ institutionId);

		List<Course> courses = query.list(); 

		// Retrieve all
		return courses;
	}

	/**
	 * Retrieves all favourite courses of a user
	 */
	public List<Course> getAllFavourite(Integer personId) {
		logger.debug("Retrieving all favourite courses of the user");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = session
				.createQuery("FROM CoursityUser as p LEFT JOIN FETCH  p.favouriteCourses WHERE p.favouriteCourses.id="
						+ personId);

		CoursityUser coursityUser = (CoursityUser) query.uniqueResult();

		// Retrieve all
		return new ArrayList<Course>(coursityUser.getFavouriteCourses());
	}
	
	/**
	 * Retrieves all course ratings of a user
	 */
	public List<Course> getRatingsFavourite(Integer personId) {
		logger.debug("Retrieving all favourite courses of the user");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = session
				.createQuery("FROM CoursityUser as p LEFT JOIN FETCH  p.favouriteCourses WHERE p.favouriteCourses.id="
						+ personId);

		CoursityUser coursityUser = (CoursityUser) query.uniqueResult();

		// Retrieve all
		return new ArrayList<Course>(coursityUser.getFavouriteCourses());
	}

	/**
	 * Retrieves all prerequisite courses of a course
	 */
	public List<Course> getAllPrerequisite(Integer courseId) {
		logger.debug("Retrieving all prerequisite courses of the course");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = session
				.createQuery("FROM Course as p LEFT JOIN FETCH  p.prerequisites WHERE p.id="
						+ courseId);

		Course course = (Course) query.uniqueResult();

		// Retrieve all
		return new ArrayList<Course>(course.getPrerequisites());
	}

	/**
	 * Retrieves all courses of an instructor
	 */
	public List<Course> getAllForInstructors(Integer instructorId) {
		logger.debug("Retrieving all courses of the instructor");
		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = session
				.createQuery("FROM Course as p LEFT JOIN FETCH  p.instructor WHERE p.instructor.id="
						+ instructorId);

		// Retrieve all
		List<Course> courses = query.list();

		// Retrieve all
		return courses;

	}
	
	
	/**
	 * Retrieves course of a user course rating
	 */
	public Course getByRating(Integer ratingId) {
		logger.debug("Retrieving course by rating");
		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = session
				.createQuery("Select p FROM Course as p LEFT JOIN FETCH p.ratings r WHERE r.id="
						+ ratingId);		
		
		//select course.id 
		//from course left join ratings
		//where ratings.id = 1
		
		// Retrieve all
		Course course = (Course) query.uniqueResult();

		// Retrieve all
		return course;
	}



	/**
	 * Retrieves all courses
	 * 
	 * @return a list of courses
	 */
	@SuppressWarnings("unchecked")
	public List<Course> getAll(String listType) {
		logger.debug("Retrieving all courses");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Create a Hibernate query (HQL)
		Query query = null;

		if (listType.equals("upcoming")) {
			query = session.createQuery("FROM Course");

		} else if (listType.equals("last_submitted")) {
			query = session.createQuery("FROM Course");

		} else {
			query = session.createQuery("FROM Course");
		}
		query.setFirstResult(0);
		query.setMaxResults(10);
		// Retrieve all
		return query.list();
	}

	/**
	 * Retrieves a single course
	 */
	public Course get(Integer id) {
		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Retrieve existing person first
		Course course = (Course) session.get(Course.class, id);

		return course;
	}

	/**
	 * Adds a new course
	 */
	public void add(Course course) {
		logger.debug("Adding new course");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Persists to db
		session.save(course);
		session.refresh(course);
	}

	/**
	 * Deletes an existing course
	 * 
	 * @param id
	 *            the id of the existing course
	 */
	public void delete(Integer id) {
		logger.debug("Deleting existing course");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Retrieve existing user first
		Course course = (Course) session.get(Course.class, id);

		// Delete
		session.delete(course);
	}

	/**
	 * Edits an existing course
	 */
	public void edit(Course course) {
		logger.debug("Editing existing course");

		// Retrieve session from Hibernate
		Session session = sessionFactory.getCurrentSession();

		// Retrieve existing course via id
		Course existingCourse = (Course) session.get(Course.class,
				course.getCourseId());

		// Assign updated values to this course
		existingCourse.setCourseDescription(course.getCourseDescription());
		existingCourse.setCourseName(course.getCourseName());
		existingCourse.setRating(course.getRating());
		existingCourse.setInitiative(course.getInitiative());
		existingCourse.setInstitution(course.getInstitution());
		existingCourse.setInstructor(course.getInstructor());
		existingCourse.setCategories(course.getCategories());
		existingCourse.setLanguages(course.getLanguages());
		existingCourse.setComments(course.getComments());
		//existingCourse.setRatings(course.getRatings());
		existingCourse.setStartingDate(course.getStartingDate());
		existingCourse.setInfo(course.getInfo());
		existingCourse.setUrl(course.getUrl());
		existingCourse.setLength(course.getLength());
		existingCourse.setEstimatedEffort(course.getEstimatedEffort());
		existingCourse.setPrerequisites(course.getPrerequisites());
		existingCourse.setRecommendedBackground(course
				.getRecommendedBackground());
		existingCourse.setCertificate(course.getCertificate());
		existingCourse.setTextbook(course.getTextbook());
		existingCourse.setCountry(course.getCountry());
		existingCourse.setPeerAssesment(course.isPeerAssesment());
		existingCourse.setTeamProjects(course.isTeamProjects());
		existingCourse.setExam(course.isExam());
		existingCourse.setVideoLectures(course.isVideoLectures());
		existingCourse.setForum(course.isForum());

		// Save updates
		session.save(existingCourse);
	}

	
}
